#ifndef __GLF_TASK_TASKCPU_H_INCLUDED__
#define __GLF_TASK_TASKCPU_H_INCLUDED__

#include <glf/task/task.h>
#include <glf/task/taskHandlerConsumePolicy.h>

// The task system use compile-time composition to create new task types and new behavior
// controlling those types.
//
// It is very important to put all your code relating to a task type in a unique file.
// Also, please make sure you test accordingly; since composition is done at 
// compile time, it is a little harder to debug and make sure the right specialization
// is used than traditional polymorphic code.

namespace glf {

// First, create a new task type (and empty struct). This tag can belong to any namespace.
struct CPU_TASK;	// General CPU tasks

// By default, a task handler will consume only one task per iteration. This policy 
// can easily be changed by specilazing the consume policy proxy class.
//
// For our cpu task, we'll drain (consume all avaialable tasks) per iteartion.
template<>
class TaskHandlerConsumePolicy<CPU_TASK> : public TaskHandlerConsumeDrain<CPU_TASK>
{
};

// You can also create more custom behavior:
//
// template<>
// class TaskHandlerConsumePolicy<SOME_TASK>
// {
//   bool Consume()
//   {
//     printf("not very useful, but very custom.\n");
//   }
// }

// For more complex behavior, you can specialize the task handler directly
//
// template<>
// class TaskHandler<SOME_TASK> : public TaskHandlerImpl<SOME_TASK>, public TaskHandlerConsumeTimeSlice<SOME_TASK>
// {
// public:
// 
//   TaskHandler()
//   {
//     printf("Custom behavior at creation.\n");
//   }
//
//   SetSomeState()
//   {
//     printf("Custom method for enriched interface.\n");
//   }
//
//   bool Consume()
//   {
//     printf("not very useful, but very custom.\n");
//   }
// }

// You can also modify the behavior of push. Since push is not a templated class,
// I didn't use a policy-based system, buh a "behavior system". Please take into
// consideration that the behavior object will be instanciated and destroyed for
// each method called. Don't put anything in the constructor and destructor.
//
// template<>
// class TaskBehavior<SOME_TASK> : public TaskDefaultBehavior<SOME_TASK>
// {
// public:
//   void Push(Task* task)
//   {
//     TaskDefaultBehavior<glitch::editor::UI_TASK>::Push(task); // Default push code
//	   printf("Warn some other system that a SOME_TASK has been pushed.\n");
//   }
// }

// Other advance feature:
//
// You can attach a specific handler to a thread. This allow you to check at run-time
// if a particular handler is attached to the current thread. If this is the case, there
// is usually no need to push the task, and this technique is mandatory if you need
// to wait on your task (as pushing a task and waiting for it on the thread which is
// supposed to execute your task will result in a dead lock).
//
// You can register a particular handler to a particular thread. This will allow to call
// TaskDirector::GetInstance().ConsumeRegisteredHandler() to consume any taks form handler
// associated to the current thread. This method is highly dynamic but slower than the static
// method used. Also, this system is used by DrainTask to make sure that draining a
// particular type of tasks doesn't starve the handlers registered on the current thread.

} // end namespace glf

#endif // __GLF_TASK_TASKTAGS_H_INCLUDED__
